package com.lzz.bottomencapsulation.net;

import android.content.Context;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.lzz.bottomencapsulation.consts.EventbusCode;
import com.lzz.bottomencapsulation.consts.NetConsts;
import com.lzz.bottomencapsulation.eventbus.MessageEvent;
import com.lzz.bottomencapsulation.manager.OaidDataManager;
import com.lzz.bottomencapsulation.manager.RiskManager;
import com.lzz.bottomencapsulation.utils.AppUtils;
import com.lzz.bottomencapsulation.utils.LUtils;
import com.lzz.bottomencapsulation.utils.SPUtils;

import org.greenrobot.eventbus.EventBus;

import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers;
import io.reactivex.rxjava3.core.Observable;
import io.reactivex.rxjava3.schedulers.Schedulers;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
import okhttp3.logging.HttpLoggingInterceptor;
import okio.Buffer;
import okio.BufferedSource;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;

/**
 * 网络请求封装
 */
public class RetrofitBase {
    private static RetrofitBase retrofitBase;
    private static Retrofit retrofit;

    /**
     * 创建单例
     */
    public static RetrofitBase getInstace(final Context context) {
        if (retrofitBase == null) {
            synchronized (RetrofitBase.class) {
                retrofitBase = new RetrofitBase(context);
            }
        }
        return retrofitBase;
    }

    OkHttpClient okHttpClient;

    private RetrofitBase(final Context context) {
        if (null == retrofit) {
            OkHttpClient.Builder builder = new OkHttpClient.Builder();
            builder.interceptors().add(AddRequestHeader(context));
            openDebugLog(builder);
            builder.connectTimeout(NetConsts.CONNECT_TIMEOU, TimeUnit.SECONDS);
            builder.readTimeout(NetConsts.CONNECT_TIMEOU, TimeUnit.SECONDS);
            builder.writeTimeout(NetConsts.CONNECT_TIMEOU, TimeUnit.SECONDS);
            okHttpClient = builder.build();
        }
    }

    /**
     * webview   请求头
     * @param context
     * @return
     */
    public static Map<String, String> getWebViewHeaderData(Context context) {
        Map<String, String> extraHeaders  = new HashMap<String, String>();
        extraHeaders.put("version", AppUtils.getVersionCode(context)+"");
//        extraHeaders.put("system", NetConsts.system);
//        extraHeaders.put("system-version",android.os.Build.VERSION.SDK_INT + "");
        extraHeaders.put("device", AppUtils.getIphoneDeviceid(context));
//        extraHeaders.put("phone-brand", android.os.Build.BRAND + "");
//        extraHeaders.put("phone-model", android.os.Build.MODEL + "");
//        extraHeaders.put("Accept", "application/vnd.api+json;version="+NetConsts.API_Version);
        String Authorization =SPUtils.getLoginToken();
        if (!TextUtils.isEmpty(Authorization)) {
            extraHeaders.put("Authorization","Bearer "+Authorization);
        }
//        String User_Type=SPUtils.getUserType();
//        if (!TextUtils.isEmpty(User_Type)) {
//            extraHeaders.put("User-Type",User_Type);
//        }
        return extraHeaders;
    }

    public Retrofit setBaseUrl(String baseUrl) {

        return retrofit = new Retrofit.Builder()
                .baseUrl(baseUrl)//ip
                .client(okHttpClient)
                .addConverterFactory(ScalarsConverterFactory.create())
                .addCallAdapterFactory(RxJava3CallAdapterFactory.create())//添加rxjava
                .addConverterFactory(GsonConverterFactory.create())
                .build();
    }


    /**
     * 开关debug  打印日志
     *
     * @param builder
     */
    private void openDebugLog(OkHttpClient.Builder builder) {
        if (NetConsts.isDebug) {
//              打印日志
            HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    if(message.length() > 4000) {
                        for(int i=0;i<message.length();i+=4000){
                            if(i+4000<message.length())
                                LUtils.e("网络请求",message.substring(i, i+4000));
                            else
                                LUtils.e("网络请求",message.substring(i, message.length()));
                        }
                    } else
                        LUtils.e("网络请求",message);
                }
            });


            httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);//设置打印日志
            builder.addInterceptor(httpLoggingInterceptor);
        }
    }


    /***
     * 添加请求头
     */
    private Interceptor AddRequestHeader(final Context context) {
        return new Interceptor() {
            @Override
            public Response intercept(Chain chain) throws IOException {
                Request original = chain.request();
                Response response=chain.proceed(getHttpHead(original,context));
                ResponseBody responseBody = response.body();
                BufferedSource source = responseBody.source();
                source.request(Long.MAX_VALUE);
                Buffer buffer = source.buffer();
                Charset charset = StandardCharsets.UTF_8;
                MediaType contentType = responseBody.contentType();
                if (contentType != null) {
                    charset = contentType.charset( StandardCharsets.UTF_8);
                }
                String bodyStr = buffer.clone().readString(charset);
                Gson gson = new Gson();
                HttpRequest httpRequest = gson.fromJson(bodyStr, HttpRequest.class);
                synchronized (getInstace(context)){
                    if (TextUtils.equals(httpRequest.getErrno(),NetConsts.CODE_401)){
                        EventBus.getDefault().post(new MessageEvent(EventbusCode.CODE_OUTLOGIN));//强制退出登录
                    }
////                        刷新token
//                        String refresh_token=SPUtils.getRefreshToken();
//                        Call<HttpRequest<token>> call=  RetrofitBase.getInstace(context).setBaseUrl(NetConsts.BASE_COM_URL).create(Apiserver.class).refreshToken(refresh_token, SPUtils.getIsGuest());
//                        retrofit2.Response<HttpRequest<token>> callresponse = call.clone().execute();
//                        if (callresponse.code()==NetConsts.CODE_200&&callresponse.body().getData()!=null&&!TextUtils.isEmpty(callresponse.body().getData().getToken())){
////                            刷新token成功
//                            String token=callresponse.body().getData().getToken();
//                            refresh_token=callresponse.body().getData().getRefresh_token();
//                            SPUtils.saveLoginToken(token);
//                            SPUtils.saveRefreshToken(refresh_token);
//                            return chain.proceed(getHttpHead(original,context));
//                        }else {
//                            刷新token失败，token失效
//                            EventBus.getDefault().post(new MessageEvent(EventbusCode.CODE_OUTLOGIN));//强制退出登录
//                        }
                    }
                return response;
            }
        };
    }

    /**
     * 组装请求头
     * @param original
     * @param context
     * @return
     */
    private Request getHttpHead(Request original, Context context) {
        Request.Builder requestBuilder = original.newBuilder()
                .addHeader("version", AppUtils.getVersionCode(context)+"")
                .addHeader("packageName",AppUtils.getPackageName(context));
//                .addHeader("Accept", getAccept())
//                .addHeader("device", AppUtils.getIphoneDeviceid(context))
//                .addHeader("system-version", android.os.Build.VERSION.SDK_INT + "")
//                .addHeader("system", NetConsts.system)
//                .addHeader("phone-brand", android.os.Build.BRAND + "")
//                .addHeader("phone-model", android.os.Build.MODEL + "");
        requestBuilder.addHeader("User-Type", "app");
        String token =SPUtils.getLoginToken();
        if (!TextUtils.isEmpty(token)) {
            requestBuilder.addHeader("token", token);
        }

        String tokenLianshanRisk = RiskManager.getInstance().getToken();
        if (!TextUtils.isEmpty(tokenLianshanRisk)) {
            requestBuilder.addHeader("tokenLianshanRisk", tokenLianshanRisk);
        }

        String oaid= OaidDataManager.getInstance().getOAID();
        if (!TextUtils.isEmpty(oaid)){
            requestBuilder.addHeader("deviceId", oaid);
        }
//        requestBuilder.removeHeader("User-Agent").addHeader("User-Agent",
//                getUserAgent(context));
        return requestBuilder.build();
    }

    private String getAccept() {
        return "application/vnd.api+json;version=" + NetConsts.API_Version;
    }

    private  String getUserAgent(Context context)
    {
        String userAgent = System.getProperty("http.agent");
        int userAgentPos = userAgent.indexOf("(");
        if (userAgentPos > 0) {
            userAgent = userAgent.substring(userAgentPos);
        }
        userAgent = "xiao an guan li/" + AppUtils.getVersionName(context) + " " + userAgent;
        StringBuffer sb = new StringBuffer();
        for (int i = 0, length = userAgent.length(); i < length; i++) {
            char c = userAgent.charAt(i);
            if (c <= '\u001f' || c >= '\u007f') {
                sb.append(String.format("\\u%04x", (int) c));
            } else {
                sb.append(c);
            }
        }

        return sb.toString();
    }


    /**
     * 网络请求   监听开始结束
     *
     * @param context
     * @param observable
     * @param callBack
     * @param <T>
     * @return
     */
    public  <T> void setSubscribe(Context context,
                                          Observable<HttpRequest<T>> observable,
                                          RequestCallBack<T> callBack) {
         observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).
                subscribe(new Subscriber<>(callBack, context));
    }

    public  <T> void setSubscribe(Context context,
                                  Observable<HttpRequest<T>> observable,
                                  RequestCallBackTwo<T> callBack) {
        observable.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).
                subscribe(new SubscriberTwo<>(callBack, context));
    }

}
